<!--
 * @ Author: mahoushaojo
 * @ Create Time: 2021-04-25 10:21:24
 * @ Modified by: yangzhiwei
 * @ Modified time: 2021-05-13 09:25:02
 * @ Description: 红包雨首页组件
 -->
 <template>
  <div class="packet_content">
    <!-- 封面模块 -->
    <cover
      v-if="startStep == 1"
      @onStart="onStart"
      :colors="colors"
      :coverImg="coverImg"
      @onClose="isClose = true"
    />
    <div
      v-if="isClose == false"
      class="packet_box"
      :style="{ background: 'url(' + backgroundImg + ') no-repeat' }"
    >
      <!-- 黑色透明遮罩层 -->
      <div class="place" v-if="showPlace && startStep == 3" ></div>
      <!-- 准备倒计时 -->
      <prepare v-if="startStep == 2" @onReady="onReady" :colors="colors" />
      <!-- 红包雨模块 -->
      <div class="red_packet" v-if="startStep == 3">
        <!-- 秒表 -->
        <second
          v-if="packetType == 1"
          class="second"
          ref="second"
          :time="time"
          :haveNumer="haveNumer"
        />
        <!-- 进度条 -->
        <rate
          v-if="packetType == 2"
          :rateNumer="haveNumer"
          :overNumber="overNumber"
        />
        <!-- 红包计数 -->
        <packetNumber :haveNumer="haveNumer" />
        <template v-for="(item, index) in packetList">
          <packet
            v-if="item.isShow"
            :key="index"
            :options="options"
            :packetImg="packetImg"
            :rare="rare"
            :pause="pause"
            @receive="receive($event, index)"
            @animationOver="animationOver(item)"
          />
        </template>
        <!-- 点击红包提示语 -->
        <tips
          ref="tips"
          :colors="colors"
          @pause="onpause"
          @onOver="onOver"
          @onCancel="onCancel"
        />
        <!-- 流星背景 -->
        <star />
        <!-- 水波纹 -->
        <template v-for="(item, index) in rippleList">
          <ripple :key="index + 'r'" :coord="item" />
        </template>
      </div>
      <!-- 奖励结算窗口 -->
      <award ref="award" :colors="colors" @iknow="iknow" />
    </div>
  </div>
</template>
 <script>
import cover from "./cover"; //红包雨开始封面
import prepare from "./prepare"; //用户准备倒计时阶段
import second from "./second"; //秒表
import rate from "./rate"; //进度条
import packet from "./packet"; //红包
import star from "./star"; //流星
import ripple from "./ripple"; //水波纹
import tips from "./tips"; //点击红包连击数
import award from "./award"; //奖励结算弹窗
import packetNumber from "./number";
export default {
  components: {
    cover,
    prepare,
    second,
    rate,
    packet,
    star,
    ripple,
    tips,
    award,
    packetNumber,
  },
  data() {
    return {
      isClose: true, //是否关闭红包雨
      startStep: 1, // 当前抢红包的阶段 1 未开始 2 准备 3开始
      packetList: [], //红包数组
      haveNumer: 0, //抢到的红包数量
      step: "", //创建红包的定时器
      rippleList: [], //波纹数组
      stats: true, //防抖状态
      count: 0, //动画结束效果计数
      stop: false, //是否停止动画
      pause: false, //是否暂停动画
      initial: 0, //用户点击红包概率递增
    };
  },
  props: {
    /**
     * 红包类型
     * *1：限制红包数量,结束条件为红包数量下落完
     * *2：不限制红包数量,结束条件为点击够足够多红包数量后结束
     */
    packetType: {
      type: Number,
      default: 2,
    },
    /**
     * 红包总数量
     */
    packetNumber: {
      type: Number,
      default: 30,
    },
    /**
     * 每次生成红包的间隔 毫秒
     */
    packetTime: {
      type: Number,
      default: 500,
    },
    /**
     * 红包点击的中奖初始概率
     * *红包类型为2时生效
     */
    probability: {
      type: Number,
      default: 30,
    },
    /**
     * 红包的配置
     */
    options: {
      default: () => {
        return {
          maxsize: 1.2, //红包大小 最大值 缩放比例
          minsize: 1, //红包大小 最小值
          imgurl: require("../../assets/H1.png"), //红包图片
          maxrotate: -45, //红包旋转 角度 最大值
          minrotate: 45, //红包旋转 最小值
          duration: 4, //红包下落到底部的速度 秒
          timing: "linear", //红包下落的运动曲线 参照animation动画
        };
      },
    },
    /**
     * 稀有红包配置项
     */
    packetImg: {
      type: Array,
    },
    /**
     * 红包雨整体背景图
     */
    backgroundImg: {
      type: String,
      default: require("@/assets/bg.png"),
    },
    /**
     * 用户点击到足够的红包个数 游戏结束
     * *指的是需要点击满足多少个红包后才结束红包雨
     * *红包类型为2 时生效
     */
    overNumber: {
      type: Number,
      default: 3,
    },
    /**
     * 活动的主题颜色
     */
    colors: {
      type: String,
      default: "#2FBC78",
    },
    /**
     * 活动开始时的封面图
     */
    coverImg: {
      type: String,
      default: "",
    },
    /**
     * 稀有红包出现的概率
     */
    rare: {
      type: Number,
      default: 50,
    },
    /**
     * 是否显示背景遮罩层
     */
    showPlace:{
      type: Boolean,
      default: true
    }
  },
  mounted() {
    /**
     * 清除定时器
     */
    window.cancelAnimationFrame(this.step);
  },
  computed: {
    /**
     * 计算所有的红包下落需要的时间
     */
    time() {
      let times = (this.packetNumber * this.packetTime) / 1000;
      return times;
    },
  },
  methods: {
    /**
     * 用户点击开始抢红包了
     * *隐藏封面图
     * *清空水波纹数组
     * *清空获得的红包数
     */
    onStart() {
      this.isClose = false;
      this.startStep = 2;
      this.packetList = [];
      this.rippleList = []
      this.haveNumer = 0;
      this.count = 0;
      this.pause = false;
      this.stop = false;
    },
    /**
     * 准备倒计时结束
     * *用户准备就绪
     */
    onReady() {
      this.startStep = 3;
      /**
       * 进入第三阶段 直接开始下红包
       * *存储初始概率值
       */
      this.initial = this.probability
      this.render();
      /**
       * 监听click事件显示波纹效果
       */
      document.addEventListener("click", (e) => {
        this.setRipple(e);
      });
    },
    /**
     * 循环生成红包
     * *如果是红包类型1 按数量生成红包
     * *如果是红包类型2, 无限循环生成红包
     */
    render() {
      if (this.pause == true) {
        clearTimeout();
        window.cancelAnimationFrame(this.step);
        return;
      }
      if (this.packetType == 1) {
        if (this.packetList.length < this.packetNumber) {
          clearTimeout();
          let obj = {
            isShow: true,
          };
          let packetTime =
            Math.random() * (this.packetTime - (this.packetTime - 100)) +
            (this.packetTime - 100);
          this.packetList.push(obj);
          setTimeout(() => {
            /**
             * 设置定时器 渲染红包
             */
            this.step = window.requestAnimationFrame(this.render);
          }, packetTime);
        } else {
          clearTimeout();
          window.cancelAnimationFrame(this.step);
        }
      } else {
        /**
         * 判断是否停止动画
         */
        if (this.stop == false) {
          clearTimeout();
          let obj = {
            isShow: true,
          };
          this.packetList.push(obj);
          let packetTime =
            Math.random() * (this.packetTime - (this.packetTime - 100)) +
            (this.packetTime - 100);
          setTimeout(() => {
            /**
             * 设置定时器 渲染红包
             */
            this.step = window.requestAnimationFrame(this.render);
          }, packetTime);
        } else {
          clearTimeout();
          window.cancelAnimationFrame(this.step);
        }
      }
    },
    receive(value, index) {
      /**
       * 红包点击事件
       * *增加提示 执行tips 提示的动画
       */
      this.$refs["tips"].setTips();
      this.packetList[index].isShow = false;
      if (this.haveNumer >= this.overNumber) {
        if (this.packetType == 2) {
          this.stop = true;
        } else {
          this.haveNumer++;
        }
      } else {
        /**
         * 如果红包类型为2
         * *根据传递的中奖概率 判断此次中奖之后才改变进度条进度
         */
        if (this.packetType == 2) {
          let random = Math.random() * 10;
          if (this.initial / 10 > random) {
            this.initial = this.probability //初始化概率值
            this.haveNumer++;
          }else{
            this.initial = this.initial + 20
          }
          /**
           * 如果进度条已满 停止红包雨
           */
          if (this.haveNumer == this.overNumber) {
            this.stop = true;
            this.$refs["award"].isShow();
          }
        } else {
          this.haveNumer++;
        }
      }
      /**
       * *如果用户点击的红包数量加下落的红包数量 大于 设定的红包数量
       * 停止红包雨
       * !只在类型1的红包雨生效
       */
      if (this.packetType == 1) {
        if (this.count + this.haveNumer == this.packetNumber) {
          this.$refs["award"].isShow();
          this.startStep = 1;
          this.isClose = true
          this.packetList = [];
        }
      }
    },
    /**
     * 设置波纹效果
     * *使用防抖效果
     */
    setRipple(e) {
      if (this.stats == true) {
        this.stats = false;
        let obj = {
          clientX: e.clientX, //减去动画光圈的半径
          clientY: e.clientY,
        };
        this.rippleList.push(obj);
        setTimeout(() => {
          this.stats = true;
        }, 160);
      }
    },
    /**
     * 监听红包雨下落
     */
    animationOver(item) {
      this.count++;
      this.$set(item, "isShow", false);
      if (this.packetType == 1) {
        if (this.count + this.haveNumer == this.packetNumber) {
          this.$refs["award"].isShow();
          this.startStep = 1;
          this.packetList = [];
        }
      }
    },
    /**
     * *暂停所有红包雨动画
     * *暂停生成红包雨
     */
    onpause() {
      this.$refs["second"].onPause();
      this.pause = true;
    },
    /**
     * *用户点击跳过动画
     * !直接结束动画直接获取所有的奖励
     * *并且让红包雨重置到最初的阶段
     */
    onOver() {
      console.log("结束所有的动画");
      this.$refs["award"].isShow();
      this.startStep = 1;
      this.packetList = [];
    },
    /**
     * *用户点击取消
     * !恢复所有的动画
     */
    onCancel() {
      this.pause = false;
      this.$refs["second"].continue();
      this.render();
    },
    /**
     * 红包雨流程完全结束
     * !向上层父组件传递最终的事件
     */
    iknow() {
      this.startStep = 1;
      this.packetList = [];
      this.isClose = true
      this.$emit("theEnd");
    },
  },
};
</script>
 <style lang="scss" scoped>
.packet_box {
  height: 100vh;
  width: 100vw;
  overflow: hidden;
  background-size: cover !important;
  background-position: center center !important;
}
.place{
  height: 100%;
  width: 100%;
  position: absolute;
  top: 0;
  left: 0;
  background: rgba($color: #000000, $alpha: .6);
}
.red_packet {
  height: 100vh;
  width: 100%;
  position: fixed;
  top: 0;
  bottom: 0;
  overflow: hidden;
  .second {
    position: absolute;
    top: 0.133333rem;
    left: 0.133333rem;
  }
  .rate {
    position: absolute;
    top: 0.666667rem;
    left: 0.266667rem;
  }
  .number {
    position: absolute;
    top: 0.266667rem;
    right: 0.266667rem;
  }
}
</style>